package com.quanyan.orderpay.web;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.quanyan.alipay.config.AlipayConfig;
import com.quanyan.alipay.protocal.AliPayBatchTransNotifyData;
import com.quanyan.alipay.protocal.AliPayRefundData;
import com.quanyan.alipay.util.AlipayNotify;
import com.quanyan.api.APIResponse;
import com.quanyan.common.encrypt.AESCoder;
import com.quanyan.common.exception.BizException;
import com.quanyan.common.utils.DateTimeUtils;
import com.quanyan.common.utils.GsonUtils;
import com.quanyan.common.utils.ServletUtils;
import com.quanyan.orderpay.constants.OrderMqConstants;
import com.quanyan.orderpay.entity.PaySuccessData;
import com.quanyan.orderpay.service.OrderProcessService;
import com.quanyan.pay.entity.AlipayAccount;
import com.quanyan.pay.entity.RefundCompleteData;
import com.quanyan.pay.entity.RefundRecord;
import com.quanyan.pay.entity.TSNRecord;
import com.quanyan.pay.enums.PayWayEnum;
import com.quanyan.pay.enums.TradeTypeEnum;
import com.quanyan.pay.exception.RespPayEnum;
import com.quanyan.pay.service.AccountService;
import com.quanyan.pay.service.PayService;
import com.quanyan.pay.service.TsnService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author songzj
 * @date 16/7/4-19:34
 */
@Controller
@RequestMapping("/alipay")
public class AlipayController {

    private Logger logger = LoggerFactory.getLogger(AlipayController.class);

    @Autowired
    private OrderProcessService orderProcessService;

    @Autowired
    private TsnService tsnService;

    @Autowired
    private AccountService accountService;

    @Autowired
    private PayService payService;

    @RequestMapping("/payNotify.api")
    public void payNotify(HttpServletRequest request, HttpServletResponse response) {
        Enumeration<String> enumeration = request.getParameterNames();
        Map<String, String> map = new HashMap<String, String>();
        StringBuffer stringBuffer = new StringBuffer();
        try {
            while (enumeration.hasMoreElements()) {
                String key = enumeration.nextElement();
                String value = request.getParameter(key);
                map.put(key, value);
                stringBuffer.append(key + "=" + value + "&");
            }
            // 打印日志start
            String trade_status = map.get("trade_status") + "";
            String orderNo = map.get("out_trade_no");
            switch (trade_status) {
                case "WAIT_BUYER_PAY":// 交易创建
                    logger.warn("订单号：{}。支付宝交易创建回调： {}", orderNo, stringBuffer.toString());
                    break;
                case "TRADE_SUCCESS":// 支付成功
                    logger.warn("订单号：{}。支付宝支付成功回调： {}", orderNo, stringBuffer.toString());
                    break;
                case "TRADE_FINISHED":// 交易成功
                    logger.warn("订单号：{}。支付宝交易成功回调： {}", orderNo, stringBuffer.toString());
                    break;
                case "TRADE_CLOSED":// 交易关闭
                    logger.warn("订单号：{}。支付宝交易关闭回调： {}", orderNo, stringBuffer.toString());
                    break;
                default:
                    logger.warn("订单号：{}。支付宝payNotify回调： {}", orderNo, stringBuffer.toString());
                    break;
            }
            // 打印日志end


            String tradeStatus = map.get("trade_status");
            boolean paySuccess = "TRADE_SUCCESS".equals(tradeStatus);

            if (paySuccess) {
                String sellerId = map.get("seller_id");
                String sellerEmail = map.get("seller_email");

                PaySuccessData paySuccessData = new PaySuccessData();
                paySuccessData.setPayTime(DateTimeUtils.convertString2Date("yyyy-MM-dd HH:mm:ss", map.get("gmt_payment")));
                paySuccessData.setPayAmount(new BigDecimal(map.get("total_fee")!=null?map.get("total_fee"):map.get("total_amount")));
                paySuccessData.setTsn(map.get("trade_no"));
                paySuccessData.setOrderNo(map.get("out_trade_no"));
                paySuccessData.setBuyerAccount(map.get("buyer_id"));
                paySuccessData.setBuyerId(map.get("buyer_email"));
                paySuccessData.setBuyerBank("");
                paySuccessData.setSellerId(sellerId);
                paySuccessData.setSellerAccount(sellerEmail);
                paySuccessData.setTradeType(TradeTypeEnum.TRADE_TYPE_ALIPAY_APP);
                paySuccessData.setSourceType(OrderMqConstants.PAY_RESEND);
                TSNRecord tsnRecord = this.tsnService.insertTsnRecord(paySuccessData.getTradeType().getPayId(),
                        TsnService.DATA_TYPE_XML, stringBuffer.toString(), paySuccessData.getTsn(),
                        paySuccessData.getOrderNo(), TsnService.TRASACTION_PAY);

                AlipayConfig alipayConfig = this.accountService.selectAlipayConfigBySellerIdAndEmail(sellerId, sellerEmail);
                if (!AlipayNotify.verify(map, alipayConfig)) {
                    logger.error("支付宝payNotify.api回调签名验证失败。verify alipay call back failure! data: {}, alipayConfig : {}", GsonUtils.toJson(map), GsonUtils.toJson(alipayConfig));
                    return;
                }

                boolean flag = this.orderProcessService.paySuccess(paySuccessData);
                if (flag) {
                    this.tsnService.updateTsnRecordStatus(tsnRecord.getId(), TsnService.STATUS_PROCESS_SUCCESS);
                    logger.warn("处理阿里支付回调成功");
                    ServletUtils.response(response, "success");
                }else{
                    logger.warn("处理业务失败");
                }
            }
        } catch (Exception e) {
            logger.error("处理阿里支付成功回调异常。requestStr=" + stringBuffer.toString(), e);
        }
    }


    @RequestMapping("/refundNotify.api")
    public void aliPayRefundSuccessCallBack(HttpServletRequest request, HttpServletResponse response) {
        Enumeration<String> enumeration = request.getParameterNames();
        Map<String, String> map = new HashMap<String, String>();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getParameter(key);
            map.put(key, value);
        }

        //通过批次号获取aliPay
        RefundRecord refundRecord = payService.selectByBatchNo(map.get("batch_no"));
        if (refundRecord == null) {
            logger.error("支付宝退款批次号异常。batch_refund_no={}，回调：{}。", map.get("batch_no"), GsonUtils.toJson(map));
            return;
        }
        logger.warn("订单号：{}。支付宝退款成功回调：{}。",refundRecord.getOrderNo(), GsonUtils.toJson(map));

        AlipayConfig alipayConfig = null;
        if(null != refundRecord.getAppId()){
            AlipayAccount alipayAccount=payService.selectAliPayAccountByAppId(refundRecord.getAppId());
            if(null!=alipayAccount){
                alipayAccount.setPrivateKey(AESCoder.decodeContent(alipayAccount.getPrivateKey()));
                alipayAccount.setPublicKey(AESCoder.decodeContent(alipayAccount.getPublicKey()));
                alipayAccount.setAliKey(AESCoder.decodeContent(alipayAccount.getAliKey()));
                alipayConfig=new AlipayConfig.Builder()
                        .setAli_public_key(alipayAccount.getPublicKey())
                        .setKey(alipayAccount.getAliKey())
                        .setPartner(alipayAccount.getPartner())
                        .setPrivate_key(alipayAccount.getPrivateKey())
                        .setSeller(alipayAccount.getSeller())
                        .build();
            }
        }
        if(null==alipayConfig){
            throw new BizException(RespPayEnum.ALIPAY_CONFIG_NOT_EXIST);
        }

        if (AliPayRefundData.verify(map, alipayConfig)) {
            String result_details = map.get("result_details");
            logger.warn(result_details);
            String result=result_details.split("\\^")[2];
            RefundCompleteData refundCompleteData =new RefundCompleteData();
            if(result.equals("SUCCESS")){
                //退款成功
                refundCompleteData.setResult("SUCCESS");
            }else{
                //退款成功
                refundCompleteData.setResult("FAIL");
                //错误码
                refundCompleteData.setErrCode(result);
            }
            refundCompleteData.setRefundId(result_details.split("\\^")[0]);
            refundCompleteData.setRefundAmount(new BigDecimal(result_details.split("\\^")[1]));
            refundCompleteData.setRefundOrderNo(refundRecord.getRefundOrderNo());
            refundCompleteData.setOrderNo(refundRecord.getOrderNo());
            refundCompleteData.setPayId(PayWayEnum.PAY_WAY_ALIPAY.getPayId());
            refundCompleteData.setRefundTime(DateTimeUtils.convertString2Date("yyyy-MM-dd HH:mm:ss", map.get("notify_time")));
            orderProcessService.refundComplateProcess(refundCompleteData);
            // boolean bool = this.apiOrderWrapper.recieveAliPayRefundNotify(result_details);
            ServletUtils.response(response, "success");
        }
    }

    /**
     * 管理后台点击批量付款后，支付宝回调到此方法
     */
    @RequestMapping(value = "/withdrawNotify.api")
    public void withdrawNotify(HttpServletRequest request, HttpServletResponse response) {

        Enumeration<String> enumeration = request.getParameterNames();
        Map<String, String> map = new HashMap<String, String>();
        StringBuffer stringBuffer = new StringBuffer();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getParameter(key);
            logger.info("key : {}, value:{}", key, value);
            map.put(key, value);
            stringBuffer.append(key + "=" + value + "&");
        }

        logger.info("提现回调返回：" + stringBuffer.toString());

        APIResponse<AlipayAccount> accountResp = payService.getAlipayAccount("2", PayWayEnum.PAY_WAY_ALIPAY.getPayId());
        if (!accountResp.isRet()) {
            return;
        }

        AlipayAccount alipayAccount = accountResp.getData();
        AlipayConfig alipayConfig = new AlipayConfig.Builder()
                .setSign_type("MD5")
                .setSeller(alipayAccount.getSeller()) //"financial7@quncaotech.com"
                .setPrivate_key(alipayAccount.getPrivateKey())
                .setPartner(alipayAccount.getPartner()) //"2088421220280410"
                .setKey(alipayAccount.getAliKey())      //"ideh4bfdz8v13oc79ljbec766nv91msy"
                .setAli_public_key(alipayAccount.getPublicKey()).build();
        logger.info("---------------------------------------alipayConfig=" + JSON.toJSONString(alipayConfig));

        logger.info("验证是否是支付宝合法请求，返回：" + AlipayNotify.verify(map, alipayConfig));
        if (AlipayNotify.verify(map, alipayConfig)) {  //验证是支付宝的合法请求
            AliPayBatchTransNotifyData notifyData = new AliPayBatchTransNotifyData();
            notifyData.setNotify_id(map.get("notify_id"));
            notifyData.setNotify_type(map.get("notify_type"));
            notifyData.setNotify_id(map.get("notify_id"));
            notifyData.setSign_type(map.get("sign_type"));
            notifyData.setSign(map.get("sign"));
            notifyData.setBatch_no(map.get("batch_no"));
            notifyData.setPay_user_id(map.get("pay_user_id"));
            notifyData.setPay_user_name(map.get("pay_user_name"));
            notifyData.setPay_account_no(map.get("pay_account_no"));
            notifyData.setSuccess_details(map.get("success_details"));
            notifyData.setFail_details(map.get("fail_details"));
            //订单业务处理
            orderProcessService.withdrawCompleteProccess(notifyData);
            ServletUtils.response(response, "success");
        }
    }
}
